package com.fili.params;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.util.Arrays;
import java.util.Vector;

/**
 * Date: Oct 30, 2005
 * Time: 2:31:05 PM
 *
 * @author Claudiu-Florin FILIMON for Borux Consulting S.R.L.
 */
public class ParametrizationEngine extends DefaultHandler
{
    private Vector<Param> params;

    private String path;

    private String text;
    private String paramName;
    private String paramType;
    private String paramMinValue;
    private String paramMaxValue;
    private String paramCurrentValue;
/*-------------------------------------------------------------------------------------
    Getters and setters
 --------------------------------------------------------------------------------------*/

/*-------------------------------------------------------------------------------------
	Constructors
 --------------------------------------------------------------------------------------*/

    public ParametrizationEngine(String path)
    {
        this.path = path;
        params = new Vector<Param>(10, 10);

        loadParams();
    }
/*-------------------------------------------------------------------------------------
    Methods
 --------------------------------------------------------------------------------------*/

    public Param getParam(String name)
    {
        for (Param p : params)
            if (name.equals(p.getParamName()))
                return p;

        return null;
    }

    private void writeTo(String leading, OutputStream os) throws IOException
    {
        String s;

        s = leading + "<com.fili.params>\n";
        XMLHelper.write(s, os);
        for (Param p : params)
        {
            s = leading + "\t<param name=\"" + p.getParamName() + "\">\n";
            XMLHelper.write(s, os);

            s = leading + "\t\t\t<type>" + p.getCurrentValue().getClass().getSimpleName() + "</type>\n";
            XMLHelper.write(s, os);

            if (p.getMinValue() != null)
            {
                s = leading + "\t\t\t<minValue>";
                if (p.getMinValue() instanceof String)
                    s += XMLHelper.quoteCharacters((String) p.getMinValue());
                else
                    s += p.getMinValue();
                s += "</minValue>\n";
                XMLHelper.write(s, os);
            }

            if (p.getMaxValue() != null)
            {
                s = leading + "\t\t\t<maxValue>";
                if (p.getMaxValue() instanceof String)
                    s += XMLHelper.quoteCharacters((String) p.getMaxValue());
                else
                    s += p.getMinValue();
                s += "</maxValue>\n";
                XMLHelper.write(s, os);
            }

            s = leading + "\t\t\t<currentValue>";
            if (p.getCurrentValue() instanceof String)
                s += XMLHelper.quoteCharacters((String) p.getCurrentValue());
            else
                s += p.getCurrentValue();
            s += "</currentValue>\n";
            XMLHelper.write(s, os);

            s = leading + "\t</param>\n";
            XMLHelper.write(s, os);
        }
        s = leading + "</com.fili.params>\n";
        XMLHelper.write(s, os);
    }

    public Param addParam(Param p)
    {
        for (Param sp : params)
        {
            if (sp.getParamName().equals(p.getParamName()))
                return sp;
        }
        params.add(p);
        return p;
    }

    public void replaceParam(Param p)
    {
        for (int i = 0; i < params.size(); i++)
            if (params.get(i).getParamName().equals(p.getParamName()))
            {
                params.remove(i);
                break;
            }

        params.add(p);
    }

    public void saveParams(String path)
    {
        try
        {
            FileOutputStream fos = new FileOutputStream(path);


            Object[] pa = params.toArray();
            Arrays.sort(pa);

            params = new Vector<Param>(pa.length);
            for (Object o : pa)
                params.add((Param) o);

            writeTo("", fos);
            fos.flush();
            fos.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void saveParams()
    {
        saveParams(path);
    }

    public void loadParams(String path)
    {
        try
        {
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = saxParserFactory.newSAXParser();
            XMLReader parser = saxParser.getXMLReader();

            parser.setContentHandler(this);

            if (new File(path).isFile())
                parser.parse(new InputSource(new FileInputStream(path)));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (ParserConfigurationException e)
        {
            e.printStackTrace();
        }
        catch (SAXException e)
        {
            e.printStackTrace();
        }

    }

    public void loadParams()
    {
        loadParams(path);
    }

/*-------------------------------------------------------------------------------------
    Overrides
 --------------------------------------------------------------------------------------*/

    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
    {
        text = "";
        if (qName.equals("param"))
        {
            for (int i = 0; i < attributes.getLength(); i++)
            {
                String aName = attributes.getQName(i);
                String aText = attributes.getValue(i);

                if (aName.equals("name"))
                    paramName = aText;
            }
        }
    }

    public void endElement(String uri, String localName, String qName) throws SAXException
    {
        text = text.trim();

        if (qName.equals("type"))
            paramType = text;
        if (qName.equals("minValue"))
            paramMinValue = text;
        if (qName.equals("maxValue"))
            paramMaxValue = text;
        if (qName.equals("currentValue"))
            paramCurrentValue = text;
        if (qName.equals("param"))
        {
            params.add(new Param(paramName, paramType, paramCurrentValue, paramMinValue, paramMaxValue));
        }
    }

    public void characters(char ch[], int start, int length) throws SAXException
    {
        text += new String(ch, start, length);
    }
/*-------------------------------------------------------------------------------------
    Implementations
 --------------------------------------------------------------------------------------*/
}
